﻿using System;
using FullDayStrategyPlugin.Common;
using Plugins;
using StockModel;

namespace FullDayStrategyPlugin
{
	internal class VolumeCalculator : IDisposable
	{
		#region Attributes

		private readonly OperationManager _operationManager;
		private Operation _lastOperation;
		private readonly EngineSettingsBase _settings;

		#endregion

		#region Public Methods

		public VolumeCalculator(OperationManager operationManager, EngineSettingsBase settings)
		{
			_operationManager = operationManager;
			_settings = settings;
			_operationManager.OperationExecuted += OperationManager_OnOperationExecuted; // Disposed
		}

		public int CalculateNewVolume()
		{
			int result;

			if (_lastOperation.ResultPercentage > _settings.ResetThreshold)
			{
				result = _settings.QuantityToBuy;
			}
			else
			{
				if (_settings.VolumeMode == VolumeMode.Disabled)
				{
					result = _lastOperation == null ? _settings.QuantityToBuy : _lastOperation.Volume;
				}
				else
				{
					if (_settings.VolumeMode == VolumeMode.Arithmetic)
					{
						result = _lastOperation == null ? _settings.QuantityToBuy : _lastOperation.Volume + _settings.VolumeIncrement;
					}
					else
					{
						result = _lastOperation == null ? _settings.QuantityToBuy : _lastOperation.Volume * _settings.VolumeIncrement;
					}

					if (_settings.MaxVolume > 0 && result > _settings.MaxVolume)
					{
						result = _settings.MaxVolume;
					}
				}
			}

			return result;
		}

		#endregion

		#region Event Handlers
		
		private void OperationManager_OnOperationExecuted(object sender, OperationExecutedEventArgs e)
		{
			_lastOperation = e.Operation;
		}
		
		#endregion

		#region IDisposable

        protected bool Disposed { get; private set; }

        private void Dispose(bool disposing)
        {
            if (!this.Disposed)
            {
                this.InternalDispose(disposing);
            }

            this.Disposed = true;
        }

        protected virtual void InternalDispose(bool disposing)
        {
            if (disposing)
            {
				_operationManager.OperationExecuted -= OperationManager_OnOperationExecuted;
			}

            // Dispose here only unmanaged objects 
            // Don’t use managed objects here because maybe 
            // they have been finalized already
        }

        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        ~VolumeCalculator()
        {
            this.Dispose(false);
        }

        #endregion
	}
}
